//
//  FormControl.m
//  iCodeMac
//
//  Created by Andrew Barry on 21/10/09.
//  Copyright 2009 Barry Computer Services. All rights reserved.
//

#import "FormEditor.h"
#import "FormControl.h"
#import "ControlPanel.h"
#import "ControlRegistry.h"

@implementation FormControl

-(id) init {
	self = [super init];
	events = [NSMutableDictionary new];
	return self;
}

-(NSView *) view
{
	return view;
}

-(void) setView: (NSView *) v
{
	view = v;
}

-(NSArray *) autocompletes {
	return [NSArray arrayWithObjects: @"name", @"left", @"top", @"width", @"height", nil];
}

-(void)loadEvent: (NSString *) name fromSave: (NSDictionary *) defn {
	NSString *source = [defn objectForKey:name];
	if (source) {
		[events setObject:source forKey:name];
	}
}

-(void)loadEvents: (NSDictionary *) defn {
	NSArray *evt = [self getEvents];
	for (int idx = 0; idx < [evt count]; idx++) {
		[self loadEvent: [evt objectAtIndex:idx] fromSave: defn];
	}
}

-(void) saveEvents: (NSMutableDictionary *) content {
	NSArray *evt = [self getEvents];
	for (int idx = 0; idx < [evt count]; idx++) {
		NSString *evtName = [evt objectAtIndex:idx];
		NSString *source = [events valueForKey:evtName];
		if (source != nil) {
			[content setObject:source forKey:evtName];
		}
	}
}

-(NSString *) propsNibName {
	return @"ViewProps";
}

-(void) setControlType: (NSString *) t
{
	controlType = [t retain];
}

-(void) setDocument: (JavascriptForm *) doc {
	formDocument = doc;
}

-(void) setOverlay: (FormEditorOverlay *) overlay {
	formOverlay = overlay;
}

-(void) setSavePos: (NSRect) pos {
	savePos = pos;
}

-(NSRect) savePos{
	return savePos;
}

-(bool) wasMoved {
	NSRect pos = [view frame];
	if (pos.origin.x != savePos.origin.x ||
		pos.origin.y != savePos.origin.y ||
		pos.size.width != savePos.size.width ||
		pos.size.height != savePos.size.height)
		return YES;
	return NO;
}

-(FormControl *)parent {
	return parent;
}

-(void)setParent: (FormControl *) newParent {
	if (newParent != parent) {
		NSRect r = [view frame];
		NSView *targetView;
		if (newParent)
			targetView = [[newParent view] contentView];
		else
			targetView = [formDocument editor];
		r = [targetView convertRect:r fromView:[view superview]];
		[view retain];
		[view removeFromSuperview];
		[view setFrame: r];
		[targetView addSubview:view];
		[view release];
		parent = newParent;
	}
}

-(void)broadcastPosition {
	NSRect r= [view frame];
	[ControlPanel updateValue:[NSNumber numberWithInt:r.origin.x] forProperty:@"left" forControl:self];
	[ControlPanel updateValue:[NSNumber numberWithInt:r.origin.y] forProperty:@"top" forControl:self];
	[ControlPanel updateValue:[NSNumber numberWithInt:r.size.width] forProperty:@"width" forControl:self];
	[ControlPanel updateValue:[NSNumber numberWithInt:r.size.height] forProperty:@"height" forControl:self];
}

-(void) moveAndReparentControl: (NSArray *) settings {
	NSRect oldPos = [view frame];
	FormControl *oldParent = parent;
	FormControl *newParent = [settings objectAtIndex:0];
	NSRect r = [[settings objectAtIndex: 1] rectValue];
	if (newParent == (id) [NSNull null])
		newParent = nil;
	
	[self setParent: newParent];
	[view setFrame: r];
	[formOverlay setNeedsDisplay:YES];
	[self broadcastPosition];
	
	[[formDocument undoManager] registerUndoWithTarget:self selector:@selector(moveAndReparentControl:) object: [NSArray arrayWithObjects: oldParent ? oldParent : (id) [NSNull null], [NSValue valueWithRect: oldPos], nil]];
}


-(void) moveControl: (NSValue *) newPos {
	NSRect oldPos = [view frame];
	NSRect r = [newPos rectValue];
	[view setFrame: r];
	[formOverlay setNeedsDisplay:YES];
	[ControlPanel updateValue:[NSNumber numberWithInt:r.origin.x] forProperty:@"left" forControl:self];
	[ControlPanel updateValue:[NSNumber numberWithInt:r.origin.y] forProperty:@"top" forControl:self];
	[ControlPanel updateValue:[NSNumber numberWithInt:r.size.width] forProperty:@"width" forControl:self];
	[ControlPanel updateValue:[NSNumber numberWithInt:r.size.height] forProperty:@"height" forControl:self];
	
	[[formDocument undoManager] registerUndoWithTarget:self selector:@selector(moveControl:) object:[NSValue valueWithRect: oldPos]];
}

-(void) saveField: (NSMutableDictionary *) content forKey:(NSString *) name {
	[content setObject: [self valueForProperty:name] forKey: name];
}

-(void) saveFields: (NSMutableDictionary *) content {
	NSRect frame = [view frame];
	
	[content setObject:controlType forKey:@"type"];
	
	if (controlName)
		[content setObject:controlName forKey:@"name"];
	
	if (parent)
		[content setObject:[parent controlName] forKey:@"parent"];
	
	//	if (clickedEvent)
	//		[content setObject:clickedEvent forKey:@"Clicked"];
	//	if (selectionChangedEvent)
	//		[content setObject:selectionChangedEvent forKey:@"SelectionChanged"];
	
	[content setObject:[NSNumber numberWithInt:frame.origin.x] forKey:@"left"];
	[content setObject:[NSNumber numberWithInt:frame.origin.y] forKey:@"top"];
	[content setObject:[NSNumber numberWithInt:frame.size.width] forKey:@"width"];
	[content setObject:[NSNumber numberWithInt:frame.size.height] forKey:@"height"];
	
	[content setObject:[NSNumber numberWithBool:lockLeft] forKey:@"lockLeft"];
	[content setObject:[NSNumber numberWithBool:lockTop] forKey:@"lockTop"];
	[content setObject:[NSNumber numberWithBool:lockRight] forKey:@"lockRight"];
	[content setObject:[NSNumber numberWithBool:lockBottom] forKey:@"lockBottom"];
	
	[content setObject:[NSNumber numberWithBool:visible] forKey:@"visible"];
	[content setObject:[NSNumber numberWithBool:enabled] forKey:@"enabled"];
	
}

-(NSDictionary *) save {
	NSMutableDictionary *content = [NSMutableDictionary new];
	[self saveFields:content];
	[self saveEvents:content];
	
	return content;
}

-(NSView *)load: (NSDictionary *) defn withFrame: (NSRect) frame {
	return nil;
}

-(void) postLoad {
}

+(FormControl *) loadFromSave: (NSDictionary *) defn  forEditor: (FormEditor *) editor {
	NSString *typeName = [defn objectForKey:@"type"];
	FormControl *ctl;
	
	ctl = [[ControlRegistry instance] controlForName: typeName];
	
	ctl->controlType = [typeName retain];
	
	ctl->controlName = [defn objectForKey:@"name"];
	
	ctl->lockLeft = [[defn objectForKey: @"lockLeft"] boolValue];
	ctl->lockTop = [[defn objectForKey: @"lockTop"] boolValue];
	ctl->lockRight = [[defn objectForKey: @"lockRight"] boolValue];
	ctl->lockBottom = [[defn objectForKey: @"lockBottom"] boolValue];
	
	NSRect frame;
	frame.origin.x = [(NSNumber *) [defn objectForKey:@"left"] intValue];
	frame.origin.y = [(NSNumber *) [defn objectForKey:@"top"] intValue];
	frame.size.width = [(NSNumber *) [defn objectForKey:@"width"] intValue];
	frame.size.height = [(NSNumber *) [defn objectForKey:@"height"] intValue];
	
	if ([defn objectForKey:@"visible"])
		ctl->visible = [[defn objectForKey:@"visible"] boolValue];
	else
		ctl->visible = true;
	
	if ([defn objectForKey:@"enabled"])
		ctl->enabled = [[defn objectForKey:@"enabled"] boolValue];
	else
		ctl->enabled = true;
	
	NSString *parentName = [defn objectForKey: @"parent"];
	
	if (parentName) {
		ctl->parent = [editor controlByName: parentName];
	}
	
	ctl->view = [ctl load: defn withFrame: (NSRect) frame];
	[ctl loadEvents:defn];
	
	[ctl updateSizing];
	return ctl;
}

-(id) valueForProperty: (NSString *) name {
	if ([name isEqualToString:@"name"]) {
		if (controlName)
			return controlName;
		else
			return @"";
	}
	if ([name isEqualToString:@"caption"]) {
		if ([controlType isEqualToString:@"label"]) {
			return [(NSTextField *) view stringValue];
		} else if ([controlType isEqualToString:@"canvas"]) {
			return @"";
		}
	} else if ([name isEqualToString:@"left"]) {
		NSRect frame = [view frame];
		return [NSNumber numberWithInt:frame.origin.x];
	} else if ([name isEqualToString:@"top"]) {
		NSRect frame = [view frame];
		return [NSNumber numberWithInt:frame.origin.y];
	} else if ([name isEqualToString:@"width"]) {
		NSRect frame = [view frame];
		return [NSNumber numberWithInt:frame.size.width];
	} else if ([name isEqualToString:@"height"]) {
		NSRect frame = [view frame];
		return [NSNumber numberWithInt:frame.size.height];
	} else if ([name isEqualToString:@"lockLeft"]) {
		return [NSNumber numberWithInt:lockLeft ? 1 : 0];
	} else if ([name isEqualToString:@"lockTop"]) {
		return [NSNumber numberWithInt:lockTop ? 1 : 0];
	} else if ([name isEqualToString:@"lockRight"]) {
		return [NSNumber numberWithInt:lockRight ? 1 : 0];
	} else if ([name isEqualToString:@"lockBottom"]) {
		return [NSNumber numberWithInt:lockBottom ? 1 : 0];
	} else if ([name isEqualToString:@"visible"]) {
		return [NSNumber numberWithInt:visible ? 1 : 0];
	} else if ([name isEqualToString:@"enabled"]) {
		return [NSNumber numberWithInt:enabled ? 1 : 0];
	}
	return nil;
}

-(void) setValue: (id) val forProperty:(NSString*) name {
	if ([name isEqualToString:@"name"]) {
		[controlName autorelease];
		controlName = [val retain];
		[formDocument rebuildObjectPopup];
	}
	else if ([name isEqualToString:@"caption"]) {
		if ([controlType isEqualToString:@"label"]) {
			[(NSTextField *) view setStringValue: val];
		}
	} else if ([name isEqualToString:@"left"]) {
		NSRect frame = [view frame];
		frame.origin.x = [val intValue];
		[view setFrame:frame];
		[formOverlay setNeedsDisplay:YES];
	} else if ([name isEqualToString:@"top"]) {
		NSRect frame = [view frame];
		frame.origin.y = [val intValue];
		[view setFrame:frame];
		[formOverlay setNeedsDisplay:YES];
	} else if ([name isEqualToString:@"width"]) {
		NSRect frame = [view frame];
		frame.size.width = [val intValue];
		[view setFrame:frame];
		[formOverlay setNeedsDisplay:YES];
	} else if ([name isEqualToString:@"height"]) {
		NSRect frame = [view frame];
		frame.size.height = [val intValue];
		[view setFrame:frame];
		[formOverlay setNeedsDisplay:YES];
	} else if ([name isEqualToString:@"lockLeft"]) {
		lockLeft = [val intValue] != 0;
		[self updateSizing];
	} else if ([name isEqualToString:@"lockTop"]) {
		lockTop = [val intValue] != 0;
		[self updateSizing];
	} else if ([name isEqualToString:@"lockRight"]) {
		lockRight = [val intValue] != 0;
		[self updateSizing];
	} else if ([name isEqualToString:@"lockBottom"]) {
		lockBottom = [val intValue] != 0;
		[self updateSizing];
	} else if ([name isEqualToString:@"visible"]) {
		visible = [val intValue] != 0;
	} else if ([name isEqualToString:@"enabled"]) {
		enabled = [val intValue] != 0;
	}
	
	[ControlPanel updateValue: val forProperty: name forControl: self];
	/*
	 if (info != nil) {
	 [info updateValue: val forProperty: name];
	 }
	 */
}

-(void) updateSizing {
	int mask = 0;
	if (lockRight && lockLeft)
		mask |= NSViewWidthSizable;
	else if (lockRight)
		mask |= NSViewMinXMargin;
	if (lockTop && lockBottom)
		mask |= NSViewHeightSizable;
	else if (lockBottom)
		mask |= NSViewMinYMargin;
	[view setAutoresizingMask: mask];
}

-(void) setControlName: (NSString *) v {
	[controlName autorelease];
	controlName = [v retain];
	[formDocument rebuildObjectPopup];
}

-(NSString *) controlName {
	return controlName;
}

-(NSString*) typeName {
	return controlType;
}

-(NSArray *) getEvents {
	if ([controlType isEqualToString:@"list"])
		return [NSArray arrayWithObjects:@"SelectionChanged", @"RowCount", @"CellValue", nil];
	else if ([controlType isEqualToString:@"canvas"])
		return [NSArray arrayWithObjects:@"Paint", @"MouseDown", @"MouseUp", @"MouseDrag", nil];
	else
		return [NSArray arrayWithObject:@"Click"];
}

-(NSString *) sourceForEvent: (NSString *) eventName {
	return [events valueForKey:eventName];
}

-(void) commitSource: (NSString *) source forEvent: (NSString *) eventName {
	[events setObject:source forKey:eventName];
}


@end
